﻿/**
 * ColorMunch 1.0: AS3 library for the Adobe Kuler API (http://code.google.com/p/colormunch/)
 *
 * ColorMunch is (c) 20009 Ben Kanizay
 * This software is released under the MIT License (http://www.opensource.org/licenses/mit-license.php)
 *
 */

/**
 * @author Ben Kanizay (http://beekay.biz)
 */

package beekay.colormunch {
	import flash.display.Sprite;
	import flash.events.EventDispatcher;

	/**
	 * Holds Kuler theme data including <code>Swatch</code> objects
	 * 
	 */
	public class Theme extends EventDispatcher {

		private var apiKey:String;
		private var kuler:Namespace;

		private var themeId:String;
		private var themeTitle:String;
		private var themeImage:String;

		private var themeLink:String;
		private var themeRating:String;
		private var themeDownloadCount:int;
		private var themeAuthor:String;
		private var themeAuthorId:String;
		private var themeTags:Array = new Array();
		private var themeCreatedDate:Date;
		private var themeEditedDate:Date;
		private var themeSprite:Sprite = null;

		private var swatches:Array = new Array();

		private var commentsFeed:ColorMunch;
		private var commentsAreLoaded:Boolean = false;
		

		/**
		 * Creates a new Theme
		 * @param themeID  The theme id
		 * @param themeTitle  The theme title
		 * @param themeImage  The url of the theme image
		 * @param themeLink  The url of the theme on the Adobe Kuler website
		 * @param themeCreatedDate  The creation date of the email (yyyy/mm/dd)
		 * @param themeEditedDate  The last edited date of the theme (yyyy/mm/dd)
		 * @param themeTags	 The theme tags
		 * @param themeRating  The theme rating
		 * @param themeDownloadCount  The theme download count
		 * @param themeAuthorId  The theme author id
		 * @param themeAuthor  The theme author name
		 * @param swatchesXML  The swatches XMLList
		 * @param apiKey Kuler API key
		 * @constructor
		 */
		public function Theme(themeId:String, themeTitle:String, themeImage:String, themeLink:String, themeCreatedDate:String, themeEditedDate:String, themeTags:String, themeRating:String, themeDownloadCount:String, themeAuthorId:String, themeAuthor:String, swatchesXML:XMLList, apiKey:String) {
			
			// set the values
			this.apiKey = apiKey;
			this.themeAuthorId = themeAuthorId;
			this.themeAuthor = themeAuthor;
			this.themeLink = themeLink;
			this.themeRating = themeRating;
			this.themeDownloadCount = parseInt(themeDownloadCount);
			this.themeId = themeId;
			this.themeTitle = themeTitle;
			this.themeImage = themeImage;
			this.kuler = new Namespace(ColorMunch.KULER_NAMESPACE);
			this.themeTags = themeTags.split(", ");

			// convert the created date value(s) into a Date object
			var year:String = themeCreatedDate.substr(0, 4);
			var month:String = themeCreatedDate.substr(4, 2);
			var day:String = themeCreatedDate.substr(6, 2);
			var dateString:String = month + "/" + day + "/" + year;
			this.themeCreatedDate = new Date(dateString);

			// convert the edited date value(s) into a Date object
			year = themeEditedDate.substr(0, 4);
			month = themeEditedDate.substr(4, 2);
			day = themeEditedDate.substr(6, 2);
			dateString = month + "/" + day + "/" + year;
			this.themeEditedDate = new Date(dateString);

			this.parseSwatchesXML(swatchesXML);
		}




		/**
		 * 
		 * Parses the XMLList of swatches from the feed result, creating a new Swatch object for each and pushing those into the swatches array
		 * 
		 * @param swatchesXML The XMLList of Kuler swatches to parse
		 * 
		 */
		private function parseSwatchesXML(swatchesXML:XMLList) : void {
			var len:int = swatchesXML.length();
			this.swatches = [];
			for (var i:int = 0; i < len; i++) {
				var swatch:XML = swatchesXML[i];
				this.swatches.push(new Swatch(
					swatch.kuler::swatchHexColor, 
					swatch.kuler::swatchColorMode, 
					swatch.kuler::swatchChannel1, 
					swatch.kuler::swatchChannel2, 
					swatch.kuler::swatchChannel3, 
					swatch.kuler::swatchChannel4, 
					swatch.kuler::swatchIndex
				));
			}
		}
		

		/**
		 * Starts the process of loading the comments for this theme
		 * <p>The following events may dispatched during the process
		 * <ul><li>ColorMunchEvent.BUSY : This Theme instance is already processing a loadThemeComments request</li>
		 * <li>ColorMunchEvent.LOAD_ERROR : A problem was encountered loading the feed</li>
		 * <li>ColorMunchEvent.RESULT_EMPTY : There were zero results returned</li>
		 * <li>ColorMunchEvent.RESULT_READY : The result has been parsed and the can now to be read (via the explicit getters)</li></ul></p>
		 * 
		 * @param startIndex (optional) A 0-based index into the list that specifies the first item to display. Default is 0, which displays the first item in the list.
 		 * @param itemsPerPage (optional) The maximum number of items to display, in the range 1..100. Default is 20.
		 * 
		 */
		public function loadThemeComments(startIndex:int = 0, itemsPerPage:int = 20) : void {
			this.commentsFeed = new ColorMunch(this.apiKey);
			this.commentsFeed.addEventListener(ColorMunchEvent.BUSY, this.onCommentsFeedBusy);
			this.commentsFeed.addEventListener(ColorMunchEvent.LOAD_ERROR, this.onCommentsLoadError);
			this.commentsFeed.addEventListener(ColorMunchEvent.RESULT_EMPTY, this.onCommentsFeedResultEmpty);
			this.commentsFeed.addEventListener(ColorMunchEvent.RESULT_READY, this.onCommentsFeedDataParsed);
			this.commentsFeed.loadComments(ColorMunch.COMMENTS_BY_THEME_ID, this.themeId, startIndex, itemsPerPage);
		}
		
		private function onCommentsFeedDataParsed(event : ColorMunchEvent) : void {
			this.commentsAreLoaded = true;
			this.dispatchEvent(new ColorMunchEvent(ColorMunchEvent.RESULT_READY, event.data));
		}

		private function onCommentsFeedResultEmpty(event : ColorMunchEvent) : void {
			this.commentsAreLoaded = true;
			this.dispatchEvent(new ColorMunchEvent(ColorMunchEvent.RESULT_EMPTY, event.data));
		}

		private function onCommentsLoadError(event : ColorMunchEvent) : void {
			this.dispatchEvent(new ColorMunchEvent(ColorMunchEvent.LOAD_ERROR, event.data));
		}

		private function onCommentsFeedBusy(event : ColorMunchEvent) : void {
			this.dispatchEvent(new ColorMunchEvent(ColorMunchEvent.BUSY, event.data));
		}

		
		

		/**
		 * Get the total number of swatches in this theme
		 * 
		 * @return Number of swatches
		 * 
		 */
		public function getSwatchCount() : int {
			return this.swatches.length;
		}
		
		/**
		 * Get the theme ID
		 * 
		 * @return Theme ID
		 * 
		 */
		public function getThemeId() : String {
			return this.themeId;
		}
		
		/**
		 * Get the theme title
		 * 
		 * @return Theme title
		 * 
		 */
		public function getThemeTitle() : String {
			return this.themeTitle;
		}
		
		/**
		 * Get the theme image (png file)
		 * <p>Note: This is only the url to the theme image</p>
		 * <p>If you'd prefer to use a vector Sprite see getThemeSprite</p>
		 * 
		 * @return String
		 * 
		 */
		public function getThemeImage() : String {
			return this.themeImage;
		}

		/**
		 * Get all the swatches in this theme
		 * 
		 * @return An array of swatches. Each array item is of type Swatch
		 * 
		 */
		public function getSwatches() : Array {
			return this.swatches;
		}

		/**
		 * Get a specific Swatch from this theme
		 * 
		 * @param index:int The array index of the swatch
		 * 
		 * @return The specified swatch
		 * 
		 */
		public function getSwatchByIndex(index:int) : Swatch {
			return this.swatches[index];
		}

		/**
		 * Get a random swatch from this theme
		 * 
		 * @return A random swatch
		 * 
		 */
		public function getRandomSwatch() : Swatch {
			var random:int =  Math.floor(Math.random() * (this.swatches.length));
			return this.swatches[random];
		}

		/**
		 * Get the link (url) to this theme on the Adobe Kuler website
		 * 
		 * @return Theme link/url
		 * 
		 */
		public function getThemeLink() : String {
			return this.themeLink;
		}
		
		/**
		 * Get the theme author's name
		 * 
		 * @return Theme author name
		 * 
		 */
		public function getThemeAuthor() : String {
			return this.themeAuthor;
		}

		/**
		 * Get the theme author's id
		 * 
		 * @return Theme author ID
		 * 
		 */
		public function getThemeAuthorId() : String {
			return this.themeAuthorId;
		}

		/**
		 * Get the theme's download count
		 * 
		 * @return Theme download count
		 * 
		 */
		public function getThemeDownloadCount() : int {
			return this.themeDownloadCount;
		}

		/**
		 * Get the theme's rating
		 * 
		 * @return Theme rating
		 * 
		 */
		public function getThemeRating() : String {
			return this.themeRating;
		}

		/**
		 * Get the theme tags
		 * 
		 * @return Theme tags. Each array item is of type String
		 * 
		 */
		public function getThemeTags() : Array {
			return this.themeTags;
		}

		/**
		 * Get the theme's created date
		 * 
		 * @return Theme created date
		 * 
		 */
		public function getThemeCreatedDate() : Date {
			return this.themeCreatedDate;
		}

		/**
		 * Get the theme's last edited date
		 * 
		 * @return Theme edited date
		 * 
		 */
		public function getThemeEditedDate() : Date {
			return this.themeEditedDate;
		}

		/**
		 * Get a theme Sprite containing child sprites of each swatch
		 * 
		 * @return Theme swatches sprite
		 * 
		 */
		public function getThemeSprite() : Sprite {
			if (this.themeSprite == null) {
				this.themeSprite = new Sprite();
				var square:Sprite;
				var swatch:Swatch;
				var xPos:Number = 0;
				for (var i:int = 0; i < this.swatches.length; i++) {
					swatch = this.swatches[i] as Swatch;
					square = swatch.getSwatchSprite();
					square.y = 0;
					square.x = xPos;
					this.themeSprite.addChild(square);
					xPos += square.width;
				}
			}
			return this.themeSprite;
		}





		/**
		 * Check if the comments for this theme have been loaded
		 * 
		 * @return <code>true</code> means the comments have already been loaded, <code>false</false> means the comments have not been loaded yet
		 * 
		 */
		public function commentsLoaded() : Boolean {
			return this.commentsAreLoaded;
		}


		/**
		 * Get the total number of comments for this theme
		 * 
		 * @return Total comments
		 * 
		 */
		public function getCommentCount() : int {
			return this.commentsFeed.getCommentCount();
		}


		/**
		 * Get all the comments for this theme
		 * 
		 * @return Comments for this theme. Each array item is of type Comment
		 * 
		 */
		public function getAllComments() : Array {
			return this.commentsFeed.getAllComments();
		}

		/**
		 * Get a specific comment for this theme
		 * 
		 * @param index The array index of the comment
		 * 
		 * @return The requested comment
		 * 
		 */
		public function getCommentByIndex(index:int) : Comment {
			return this.commentsFeed.getCommentByIndex(index);
		}

		/**
		 * Get a random comment for this theme
		 * 
		 * @return Random comment
		 * 
		 */
		public function getRandomComment() : Comment {
			return this.commentsFeed.getRandomComment();
		}

	}
}
